VFG.Util = function() {
}
VFG.Util.ECE=new Cesium.ECEF();
VFG.Util.getUuid = function() {
	var s = [];
	var hexDigits = "0123456789abcdef";
	for (var i = 0; i < 36; i++) {
		s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
	}
	s[14] = "4";
	s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
	s[8] = s[13] = s[18] = s[23] = "-";
	var uuid = s.join("");
	return uuid;
}
/**
* 校验只要是数字（包含正负整数，0以及正负浮点数）就返回true
**/

VFG.Util.isNumber=function(val){
    return typeof value === 'number' && !isNaN(value);
}

VFG.Util.getVisualAngle = function(viewer) {
	return {
		heading : Cesium.Math.toDegrees(viewer.camera.heading).toFixed(2),
		pitch : Cesium.Math.toDegrees(viewer.camera.pitch).toFixed(2),
		roll :  Cesium.Math.toDegrees(viewer.camera.roll).toFixed(2),
		position : this.getLnLaFormC3(viewer, viewer.camera.position)
	}
}

VFG.Util.getLnLaFormC3 = function(viewer, cartesian3) {
	var ellipsoid = viewer.scene.globe.ellipsoid;
	var cartographic = ellipsoid.cartesianToCartographic(cartesian3);
	var lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(7);
	var lng = Cesium.Math.toDegrees(cartographic.longitude).toFixed(7);
	var alt = cartographic.height.toFixed(2);
	return {
		x : lng,
		y : lat,
		z : alt
	};
}


VFG.Util.getScreenToC3 =function(viewer, position, noPickEntity) {
	
	var scene=viewer.scene;
	
    var cartesian;

    //在模型上提取坐标   
    var pickedObject;
    try {
        pickedObject = scene.pick(position, 5, 5);
    } catch (e) {
        console.log("scene.pick 拾取位置时异常");
    }

    if (scene.pickPositionSupported && Cesium.defined(pickedObject)) {
        var pcEntity = this.hasPickedModel(pickedObject, noPickEntity);
        if (!pcEntity) {
            cartesian = scene.pickPosition(position);
            if (Cesium.defined(cartesian)) {
                var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
                if (cartographic.height >= 0) return cartesian;
                if (!Cesium.defined(pickedObject.id) && cartographic.height >= -500) return cartesian;
            } else {
            }
        } else {
        	//cartesian = this.getScreenToC3(viewer, position, noPickEntity);
        }
    } else {}

    //onlyPickModelPosition是在 ViewerEx 中定义的对外属性
    //通过 viewer.mars.onlyPickModelPosition 进行修改
    if (scene.onlyPickModelPosition) return cartesian; //只取模型上的时候，不继续读取了


    //测试scene.pickPosition和globe.pick的适用场景 https://zhuanlan.zhihu.com/p/44767866
    //1. globe.pick的结果相对稳定准确，不论地形深度检测开启与否，不论加载的是默认地形还是别的地形数据；
    //2. scene.pickPosition只有在开启地形深度检测，且不使用默认地形时是准确的。
    //注意点： 1. globe.pick只能求交地形； 2. scene.pickPosition不仅可以求交地形，还可以求交除地形以外其他所有写深度的物体。

    //提取鼠标点的地理坐标 
    if (scene.mode === Cesium.SceneMode.SCENE3D) {
        //三维模式下
        var pickRay = scene.camera.getPickRay(position);
        cartesian = scene.globe.pick(pickRay, scene);
    } else {
        //二维模式下
        cartesian = scene.camera.pickEllipsoid(position, scene.globe.ellipsoid);
    }

    if (Cesium.defined(cartesian) && scene.camera.positionCartographic.height < 10000) {
        var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        // console.log(cartographic.height);
        if (cartographic.height < -5000) return null; //屏蔽无效值
    }

    return cartesian;
}


/**
 * 屏幕坐标转世界坐标
 */
/*VFG.Util.getScreenToC3 = function(viewer, position, noPickEntity) {
	var scene = viewer.scene;
	var cartesian3;
	if (scene.mode !== Cesium.SceneMode.MORPHING) {
		var pickedObject = scene.pick(position);
		if (scene.pickPositionSupported && Cesium.defined(pickedObject)) {
			if (!this.hasPickedModel(pickedObject, noPickEntity)) {
				cartesian3 = viewer.scene.pickPosition(position);
				if (Cesium.defined(cartesian3)) {
					var height = Cesium.Cartographic.fromCartesian(cartesian3).height;
					var lat = Cesium.Math.toDegrees(Cesium.Cartographic
							.fromCartesian(cartesian3).latitude);
					var lng = Cesium.Math.toDegrees(Cesium.Cartographic
							.fromCartesian(cartesian3).longitude);
					return viewer.scene.clampToHeight(cartesian3);
				}
			}
		}
	}

	// 获取地形表面的经纬度高程坐标：
	if (!Cesium.defined(cartesian3) && (viewer.scene)) {
		var ray = viewer.camera.getPickRay(position);
		if (Cesium.defined(ray)) {
			cartesian3 = viewer.scene.globe.pick(ray, viewer.scene);
			if (Cesium.defined(cartesian3)) {
				var height = Cesium.Cartographic.fromCartesian(cartesian3).height;
				var lat = Cesium.Math.toDegrees(Cesium.Cartographic
						.fromCartesian(cartesian3).latitude);
				var lng = Cesium.Math.toDegrees(Cesium.Cartographic
						.fromCartesian(cartesian3).longitude);
				return Cesium.Cartesian3.fromDegrees(lng, lat,
						height > 0 ? height : 0);
			}
		}

	}

	// 二维坐标，获取椭球体表面的经纬度坐标：
	if (!Cesium.defined(cartesian3)) {
		cartesian3 = viewer.scene.camera.pickEllipsoid(position,
				viewer.scene.globe.ellipsoid);
		return cartesian3;
	}
	return cartesian3;
}*/

VFG.Util.hasPickedModel = function(pickedObject, noPickEntity) {
	if( Cesium.defined(pickedObject) && Cesium.defined(noPickEntity)){
		if(Cesium.defined(noPickEntity.id) && Cesium.defined(pickedObject.id)){
			if(Cesium.defined(noPickEntity.id.id) && Cesium.defined(pickedObject.id.id) && noPickEntity.id.id==pickedObject.id.id){
				return true
			}
			else if(noPickEntity.id==pickedObject.id){
				return true
			}
		}
	}
	return false;
}

VFG.Util.getScreenToLnLa = function(viewer, position, noPickEntity) {
	let cartesian3 = VFG.Util.getScreenToC3(viewer, position, noPickEntity);
	if (!Cesium.defined(cartesian3)) {
		return;
	}

	let LnLa = VFG.Util.getLnLaFormC3(viewer, cartesian3);
	if (Cesium.defined(LnLa)) {
		return LnLa;
	}
};

VFG.Util.getLnLaToC3 = function(position) {
	return  Cesium.Cartesian3.fromDegrees(position.x*1, position.y*1,position.z*1);
};

VFG.Util.getC3ToLnLa = function(viewer,cartesian3) {
	var ellipsoid=viewer.scene.globe.ellipsoid;
	var cartographic=ellipsoid.cartesianToCartographic(cartesian3);
	var lat=Cesium.Math.toDegrees(cartographic.latitude).toFixed(7);
	var lng=Cesium.Math.toDegrees(cartographic.longitude).toFixed(7);
	var alt=cartographic.height.toFixed(2);
	return {
		x:lng,
		y:lat,
		z:alt
	};
}

/**
 * viewer:viewer cameraPosition:起点 position:目标
 */
VFG.Util.getHeadingPitchRoll = function(viewer,cameraPosition, position) {
    var e = cameraPosition,
    t = position,
    i = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3), new Cesium.Cartesian3),
    a = Cesium.Cartesian3.normalize(e, new Cesium.Cartesian3),
    n = new Cesium.Camera(viewer.scene);
    n.position = e,
    n.direction = i,
    n.up = a,
    i = n.directionWC,
    a = n.upWC;
    var r = n.rightWC,
    o = new Cesium.Cartesian3,
    l = new Cesium.Matrix3,
    u = new Cesium.Quaternion;
    r = Cesium.Cartesian3.negate(r, o);
    var d = l;
    Cesium.Matrix3.setColumn(d, 0, r, d),
    Cesium.Matrix3.setColumn(d, 1, a, d),
    Cesium.Matrix3.setColumn(d, 2, i, d);
    var c = Cesium.Quaternion.fromRotationMatrix(d, u);
    var hpr = Cesium.HeadingPitchRoll.fromQuaternion(c);
	var heading = Cesium.Math.toDegrees(hpr.heading).toFixed(2);
	var pitch = Cesium.Math.toDegrees(hpr.pitch).toFixed(2);
	var roll = Cesium.Math.toDegrees(hpr.roll).toFixed(2);
	return hpr;
/*	return {
		heading:heading,
		pitch:pitch,
		roll:roll,
	}*/
	
};

VFG.Util.getDistance = function(satrt, end) {
	var geodesic = new Cesium.EllipsoidGeodesic();
	geodesic.setEndPoints(satrt, end);
	var distance = geodesic.surfaceDistance
	return distance;
}

//空间两点距离计算函数
VFG.Util.getSpaceDistance=function(position1,position2){
	var distance = 0;
    var point1cartographic = Cesium.Cartographic.fromCartesian(VFG.Util.getLnLaToC3(position1));
    var point2cartographic = Cesium.Cartographic.fromCartesian(VFG.Util.getLnLaToC3(position2));
    /** 根据经纬度计算出距离* */
    var geodesic = new Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(point1cartographic, point2cartographic);
    var s = geodesic.surfaceDistance;
    // 返回两点之间的距离
    s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
    distance = distance + s;
    return distance.toFixed(2);
}

/**
 * 飞行
 * {
 *  destination：{
 * 		x:0,
 * 		y:0,
 * 		z:0
 * },
 * 	orientation:{
 * 		heading"0,
 * 		pitch:0,
 * 		roll:0,
 * 	}
 * }
 */
VFG.Util.flyTo = function(viewer, option) {
	viewer.camera
			.flyTo({
				destination : Cesium.Cartesian3.fromDegrees(option.position.x,
						option.position.y, option.position.z),
				orientation : {
					heading : Cesium.Math
							.toRadians(option.orientation
									&& option.orientation.heading ? option.orientation.heading
									: 0),
					pitch : Cesium.Math
							.toRadians(option.orientation
									&& option.orientation.pitch ? option.orientation.pitch
									: 0),
					roll : Cesium.Math
							.toRadians(option.orientation
									&& option.orientation.roll ? option.orientation.roll
									: 0),
				}
			});
}

VFG.Util.getDistanceDisplayCondition = function(x,y) {
	var _this=this;
	if(Cesium.defined(x) && Cesium.defined(y) ){
		return new Cesium.DistanceDisplayCondition(x*1,y*1)
	}
	return null;
};

/**

 * 在坐标基础海拔上增加指定的海拔高度值

 * @param {Array} positions Cartesian3类型的数组

 * @param {Number} height 高度值

 * @return {Array} Cartesian3类型的数组

 */
VFG.Util.addPositionsHeight=function(positions, addHeight) {
    addHeight = Number(addHeight) || 0;
    if (isNaN(addHeight) || addHeight == 0) return positions;
    if (positions instanceof Array) {
        var arr = [];
        for (var i = 0, len = positions.length; i < len; i++) {
            var car = Cesium.Cartographic.fromCartesian(positions[i]);
            var point = Cesium.Cartesian3.fromRadians(car.longitude, car.latitude, car.height + addHeight);
            arr.push(point);
        }
        return arr;
    } else {
        var car = Cesium.Cartographic.fromCartesian(positions);
        return Cesium.Cartesian3.fromRadians(car.longitude, car.latitude, car.height + addHeight);
    }
}

VFG.Util.pick=function(viewer,position){
	if(Cesium.defined(viewer) && Cesium.defined(position)){
		let obj=viewer.scene.pick(position);
		if(Cesium.defined(obj)){
			if(Cesium.defined(obj.id) && (obj.id instanceof Cesium.Entity)){
				return obj;
			}
			else if(Cesium.defined(obj.primitive) && (obj.primitive instanceof Cesium.Billboard) && Cesium.defined(obj.id)){
				return obj;
			}
			else if(Cesium.defined(obj.primitive) && (obj.primitive instanceof Cesium.Label) && Cesium.defined(obj.id)){
				return obj;
			}
			else if(Cesium.defined(obj.primitive) && (obj.primitive instanceof Cesium.Primitive) && Cesium.defined(obj.id)){
				return obj;
			}
			else if (obj instanceof Cesium.Cesium3DTileFeature){
/*		        var propertyNames = obj.getPropertyNames();
		        var length = propertyNames.length;
		        for (var i = 0; i < length; ++i) {
		            var propertyName = propertyNames[i];
		            console.log(propertyName + ': ' + obj.getProperty(propertyName));
		        }*/
		        //obj.show=false;
		        return obj;
			}
			else{
				return obj;
			}
		}
	}
	return null;
}

VFG.Util.exportToImg=function(viewer,width,height){
	let canvas = viewer.scene.canvas;
	var imageWidth = width?width:800;
	let image = Canvas2Image.convertToImage(canvas, width, height,'png');
    return image.src;
}

VFG.Util.formatNum=function(num,digits){
	 return Number(Number(num).toFixed(digits || 0));
}

VFG.Util.package=function(viewer,option){
	if('rectangular'===option.type){
		return new VFG.Sensor(viewer,option);
	}
	else if('GLB'===option.type || 'GLTF'===option.type){
		return new VFG.PModel(viewer,option);
	}
}

VFG.Util.getTargetPosition=function(position,option){
	let TargetPosition=VFG.Util.ECE.enu_to_ecef({ 
		longitude:position.x*1, 
		latitude:position.y*1, 
		altitude:position.z*1
	},
	{ 
		distance: option.far*1, 
		azimuth:option.heading*1, 
		elevation:option.pitch*1
	});
	if(TargetPosition){
		return {
			x:TargetPosition.longitude,
			y:TargetPosition.latitude,
			z:TargetPosition.altitude,
		}
	}
}

VFG.Util.getHeading=function(position1, position2){
	let pointA=Cesium.Cartesian3.fromDegrees(position1.x*1, position1.y*1,position1.z*1)
	let pointB=Cesium.Cartesian3.fromDegrees(position2.x*1, position2.y*1,position2.z*1)
    let transform = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
	let positionvector = Cesium.Cartesian3.subtract(pointB, pointA, new Cesium.Cartesian3());
	let vector = Cesium.Matrix4.multiplyByPointAsVector(Cesium.Matrix4.inverse(transform, new Cesium.Matrix4()), positionvector, new Cesium.Cartesian3());
	let direction = Cesium.Cartesian3.normalize(vector, new Cesium.Cartesian3());
	let heading = Math.atan2(direction.y, direction.x) - Cesium.Math.PI_OVER_TWO;
    return Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading);
}

VFG.Util.getPitch=function(position1, position2){
	let pointA=Cesium.Cartesian3.fromDegrees(position1.x*1, position1.y*1,position1.z*1)
	let pointB=Cesium.Cartesian3.fromDegrees(position2.x*1, position2.y*1,position2.z*1)
    let transfrom = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
    const vector = Cesium.Cartesian3.subtract(pointB, pointA, new Cesium.Cartesian3());
    let direction = Cesium.Matrix4.multiplyByPointAsVector(Cesium.Matrix4.inverse(transfrom, transfrom), vector, vector);
    Cesium.Cartesian3.normalize(direction, direction);
    return Cesium.Math.PI_OVER_TWO - Cesium.Math.acosClamped(direction.z);
}

VFG.Util.getAngle=function(a,b,c){
	let p1=Cesium.Cartesian3.fromDegrees(a.x*1, a.y*1,a.z*1)
	let p2=Cesium.Cartesian3.fromDegrees(b.x*1, b.y*1,b.z*1)
	let p3=Cesium.Cartesian3.fromDegrees(c.x*1, c.y*1,c.z*1)
	var c1 = Cesium.Cartesian3.subtract(p2, p1, new Cesium.Cartesian3());
	var c2 = Cesium.Cartesian3.subtract(p3, p1, new Cesium.Cartesian3());
	var angle = Cesium.Cartesian3.angleBetween(c1, c2);
	return angle;
}

//获取模型的中心点信息
VFG.Util.getCenterForModel=function(tileset, transform) {
    var result = {};
    //记录模型原始的中心点
    var boundingSphere = tileset.boundingSphere;
    var position = boundingSphere.center;
    var catographic = Cesium.Cartographic.fromCartesian(position);

    var height = Number(catographic.height.toFixed(2));
    var longitude = Number(Cesium.Math.toDegrees(catographic.longitude).toFixed(6));
    var latitude = Number(Cesium.Math.toDegrees(catographic.latitude).toFixed(6));
    result = { x: longitude, y: latitude, z: height };

    //console.log("模型内部原始位置:" + JSON.stringify(result));

    //如果tileset自带世界矩阵矩阵，那么计算放置的经纬度和heading
    if (transform) {
        var matrix = Cesium.Matrix4.fromArray(tileset._root.transform);
        var pos = Cesium.Matrix4.getTranslation(matrix, new Cesium.Cartesian3());
        var wpos = Cesium.Cartographic.fromCartesian(pos);
        if (Cesium.defined(wpos)) {
            result.x = Number(Cesium.Math.toDegrees(wpos.longitude).toFixed(6));
            result.y = Number(Cesium.Math.toDegrees(wpos.latitude).toFixed(6));
            result.z = Number(wpos.height.toFixed(2));

            //取旋转矩阵
            var rotmat = Cesium.Matrix4.getMatrix3(matrix, new Cesium.Matrix3());
            //默认的旋转矩阵
            var defrotmat = Cesium.Matrix4.getMatrix3(Cesium.Transforms.eastNorthUpToFixedFrame(pos), new Cesium.Matrix3());

            //计算rotmat 的x轴，在defrotmat 上 旋转
            var xaxis = Cesium.Matrix3.getColumn(defrotmat, 0, new Cesium.Cartesian3());
            var yaxis = Cesium.Matrix3.getColumn(defrotmat, 1, new Cesium.Cartesian3());
            var zaxis = Cesium.Matrix3.getColumn(defrotmat, 2, new Cesium.Cartesian3());

            var dir = Cesium.Matrix3.getColumn(rotmat, 0, new Cesium.Cartesian3());

            dir = Cesium.Cartesian3.cross(dir, zaxis, dir);
            dir = Cesium.Cartesian3.cross(zaxis, dir, dir);
            dir = Cesium.Cartesian3.normalize(dir, dir);

            var heading = Cesium.Cartesian3.angleBetween(xaxis, dir);

            var ay = Cesium.Cartesian3.angleBetween(yaxis, dir);

            if (ay > Math.PI * 0.5) {
                heading = 2 * Math.PI - heading;
            }
            result.rotation_x = 0;
            result.rotation_y = 0;
            result.rotation_z = Number(Cesium.Math.toDegrees(heading).toFixed(1));

            result.heading = result.rotation_z; //兼容v1老版本

           // console.log("模型内部世界矩阵:" + JSON.stringify(result));
        }
    }

    return result;
}

VFG.Util.addPositionHeight=function(cartesian, height) {
    var carto = Cesium.Cartographic.fromCartesian(cartesian);
    if (height != 0) {
        var positionNew = Cesium.Cartesian3.fromRadians(carto.longitude, carto.latitude, carto.height+height);
        return positionNew;
    }
    return cartesian;
}

VFG.Util.formatNum=function(num, digits) {
    return Number(Number(num).toFixed(digits || 0));
}
